<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/11/27
 * Time: 14:37
 */

namespace App\Extensions;


class MeiTuanShanGou
{

    /**
     * 美团闪购接口文档地址：https://open-shangou.meituan.com/home/doc/market/100
     * 美团外卖商家文档地址：https://waimaie.meituan.com/new_fe/login#/login
     */

    /*******外部传递进来的参数*********/
    protected $url;
    protected $requestMethod;
    protected $requestParam;
    protected $systemParam = [
        'app_id' => '',//默认的店铺id
        'app_secret' => '',//默认的店铺secret
        'timestamp' => ''
    ];
    /*******外部传递进来的参数*********/


    /*******内部使用参数*********/
    protected $sign;
    /*******内部使用参数*********/


    /*******返回值参数*********/
    protected $responseCode;//相应code:200-成功|201-请求失败|其他
    protected $responseError;//错误内容
    protected $responseOriginalData;//原始请求参数
    protected $responseDecodeOriginalData;//decode解析的参数
    protected $responseParseData;//获取解析的data值
    /*******返回值参数*********/



    /**
     * MeituanShangou constructor.
     * @param $url
     * @param string $requestMethod
     * @param array $requestParam
     */
    public function __construct($url = '', $requestMethod = 'get', $requestParam = [])
    {
        $this->url = $url;
        $this->requestMethod = $requestMethod;
        $this->requestParam = $requestParam;
    }

    /**
     * 设置appId
     * @param $appId
     *
     * @return void
     * @throws
     */
    public function setAppId($appId)
    {
        $this->systemParam['app_id'] = $appId;
    }

    /**
     * 设置appSecret
     * @param $appSecret
     *
     * @return void
     * @throws
     */
    public function setAppSecret($appSecret)
    {
        $this->systemParam['app_secret'] = $appSecret;
    }

    /**
     * 设置请求接口地址
     * @param $url
     *
     * @return void
     * @throws
     */
    public function setUrl($url)
    {
        $this->url = $url;
    }


    /**
     * 设置请求参数
     * @param $requestParam
     *
     * @return void
     * @throws
     */
    public function setRequestParam($requestParam)
    {
        $this->requestParam = $requestParam;
    }

    /**
     * 获得相应请求码
     */
    public function getResponseCode()
    {
        return $this->responseCode;
    }

    /**
     * 获得报错信息
     */
    public function getResponseError()
    {
        return $this->responseError;
    }

    /**
     * 获得原始数据
     */
    public function getResponseOriginalData()
    {
        return $this->responseOriginalData;
    }

    /**
     * 获得解码后的原始数据
     */
    public function getResponseDecodeOriginalData()
    {
        return $this->responseDecodeOriginalData;
    }

    /**
     * 获得解析后的data
     */
    public function getResponseParseData()
    {
        return $this->responseParseData;
    }

    /**
     * 向目标地址请求
     */
    public function doRequest()
    {
        $response = [
            'status' => -1,
            'code' => 0,
            'message' => '',
            'data' => null
        ];
        $this->setSystemParam();
        $curlRes = $this->curlRequest($this->genUrl(), $this->requestParam, $this->requestMethod);
        if ($curlRes['status']) {
            //执行成功
            $meiTuanShanGouResponse = json_decode($curlRes['data'], true);
            if (isset($meiTuanShanGouResponse['error'])) {
                //美团闪购报错
                $response['status'] = 2;
                $response['code'] = $meiTuanShanGouResponse['error']['code'];
                $response['message'] = '请求失败:' . $meiTuanShanGouResponse['error']['msg'];
                $response['data'] = $meiTuanShanGouResponse['error'];
            } else {
                //美团闪购成功
                $response['status'] = 1;
                $response['code'] = 200;
                $response['message'] = 'success';
                $response['data'] = $curlRes['data'];
            }
        } else {
            //执行失败
            $response['message'] = $curlRes['message'];
        }
        $this->analysisResponseData($response);
    }

    /**
     * 设置系统参数
     * @param
     *
     * @return void
     * @throws
     */
    protected function setSystemParam()
    {
        $this->systemParam['timestamp'] = time();
    }

    /**
     * 获得签名
     *
     * @return string
     * @throws
     */
    protected function genSign()
    {
        $url = $this->url;
        $systemParam = $this->systemParam;
        $requestParam = $this->requestParam;

        $allParam = array_merge($systemParam, $requestParam);
        ksort($allParam);
        $str = '';
        foreach ($allParam as $key => $val) {
            if ($key != 'app_secret') {
                $str .= '&' . $key . '=' . $val;
            }
        }
        $str = ltrim($str, '&');
        $url = $url . '?' . $str . $systemParam['app_secret'];

        $sign = md5($url);

        $strToUtf8 = function ($str) {
            $encode = mb_detect_encoding($str, array("ASCII",'UTF-8',"GB2312","GBK",'BIG5'));
            if($encode == 'UTF-8'){
                return $str;
            }else{
                return mb_convert_encoding($str, 'UTF-8', $encode);
            }
        };

        return $this->sign = $strToUtf8($sign);
    }

    /**
     * 获得最终地址
     * @return string
     * @throws
     */
    protected function genUrl()
    {
        $requestMethod = $this->requestMethod;
        $url = $this->url;
        $this->genSign();
        $systemParam = $this->systemParam;
        $requestParam = $this->requestParam;

        if (strtolower($requestMethod) == 'get') {
            $str = 'app_id=' . $systemParam['app_id'] . '&timestamp=' . $systemParam['timestamp'];
            foreach ($requestParam as $key => $val) {
                $str .= '&' . $key . '=' . urlencode($val);
            }
            $str = ltrim($str, '&');
            $baseUrl = $url . '?' . $str . '&sig=' . $this->sign;
            return $baseUrl;
        } else {
            ksort($systemParam);
            $str = '';
            foreach ($systemParam as $key => $val) {
                if ($key != 'app_secret') {
                    $str .= '&' . $key . '=' . $val;
                }
            }
            $str = ltrim($str, '&');
            $baseUrl = $url . '?' . $str . '&sig=' . $this->sign;
            return $baseUrl;
        }
    }

    /**
     * curl 请求
     * @param $url url请求地址
     * @param $param post参数
     * @param $method 请求方法
     *
     * @return mixed
     * @throws
     */
    protected function curlRequest($url, $param = [], $method = 'get')
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);//URL 地址
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//FALSE禁止cURL验证对等证书
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);//设置为1是检查服务器SSL证书中是否存在一个公用名
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);//TRUE 将curl_exec()获取的信息以字符串返回，而不是直接输出。
        curl_setopt($ch, CURLOPT_TIMEOUT, 20);//超时设置,以秒为单位

        if (strtolower($method) == 'post') {
            curl_setopt($ch, CURLOPT_POST, TRUE);//TRUE时会发送POST请求,类型为：application/x-www-form-urlencoded，是 HTML 表单提交时最常见的一种
            curl_setopt($ch, CURLOPT_POSTFIELDS, $param);//全部数据使用HTTP协议中的 "POST" 操作来发送
        }

        $output = curl_exec($ch);//执行命令

        $result = [
            'status' => true,
            'message' => '',
            'data' => []
        ];

        if (curl_error($ch)) {
            $result['status'] = false;
            $result['message'] = 'Error: ' . curl_error($ch);
        } else {

            $result['data'] = $output;
        }

        curl_close($ch);

        return $result;
    }

    /**
     * 解析返回值
     * @param array $responseData
     *
     * @return void
     * @throws
     */
    protected function analysisResponseData(array $responseData)
    {
        switch ($responseData['status']) {
            case -1://底层未正确请求到美团闪购
                $this->responseCode = 201;
                $this->responseError = $responseData['message'];
                break;
            case 1://成功请求到美团，但是调用接口失败
                $this->responseCode = 200;
                $this->responseOriginalData = $responseData['data'];
                $this->responseDecodeOriginalData = json_decode($responseData['data'], true);
                $this->responseParseData = json_decode($responseData['data'], true)['data'];
                break;
            case 2://成功请求到美团，且调用接口成功
                $this->responseCode = $responseData['code'];
                $this->responseError = $responseData['message'];
                break;
            default://返回值异常
        }

    }
}

/*
//使用示例
function example()
{
    //获取应用已绑定门店的三方门店ID
    $url = 'https://waimaiopen.meituan.com/api/v1/poi/getids';
    $requestMethod = 'get';
    $requestParam = [];


    //门店设置为营业状态
    $url = 'https://waimaiopen.meituan.com/api/v1/poi/open';
    $requestMethod = 'post';
    $requestParam = ['app_poi_code' => '5681_2701618'];

    $mtsg = new MeiTuanShanGou($url, $requestMethod, $requestParam);
    $mtsg->doRequest();
    if ($mtsg->getResponseCode() != 200) {
        //执行错误
        var_dump($mtsg->getResponseError());
    } else {
        //执行正常
        var_dump($mtsg->getResponseParseData());
    }
}
*/
